//
// Created by martin on 4/30/22.
//

#include <stdio.h>
#include <stdlib.h>
#include <sys/sendfile.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/socket.h>
#include <strings.h>
#include <errno.h>
#include <arpa/inet.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
    if (argc <= 3) {
        printf("usage: %s ip_address port_number filename\n", basename(argv[0]));
        return 1;
    }

    const char* ip = argv[1];
    int port = atoi(argv[2]);
    const char* file_name=  argv[3] ;

    int filefd = open(file_name, O_RDONLY);
    assert(filefd > 0);
    struct stat st;
    fstat(filefd, &st);

    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    inet_pton(AF_INET, ip, &addr.sin_addr);
    addr.sin_port = htons(static_cast<uint16_t>(port));

    int sock = socket(PF_INET, SOCK_STREAM, 0);
    assert(sock >= 0);
    int on = 1;
    setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));

    int ret = bind(sock, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));
    assert(ret != -1);

    ret = listen(sock, 5);
    assert(ret != -1);

    struct sockaddr_in client;
    socklen_t client_addrlen = sizeof(client);
    int connfd = accept(sock, reinterpret_cast<struct sockaddr*>(&client), &client_addrlen);
    if (connfd < 0) {
        printf("errno is: %d\n", errno);
    }
    else {
        // sendfile from filefd to connfd
        sendfile(connfd, filefd, NULL, static_cast<size_t>(st.st_size));
        close(connfd);
    }

    close(filefd);
    close(sock);
    return 0;
}
